package com.wn.sk.order.core.consumer;

import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.rabbitmq.client.Channel;
import com.wn.common.api.order.contants.OrderConstant;
import com.wn.common.api.order.dto.OrderPayDto;
import com.wn.common.api.order.vo.OrderVo;
import com.wn.sk.order.core.entity.Order;
import com.wn.sk.order.core.service.IOrderService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.ExchangeTypes;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.messaging.handler.annotation.Payload;
import org.springframework.stereotype.Component;

import java.io.IOException;

/**
 * 订单消费者
 *
 * 01 如果长时间 的为付款 会修改订单状态,把状态改为 无效订单
 * 02 redis 中的描述库存 恢复
 */
@Component
@Slf4j
public class OrderConsumer {
    @Autowired
    private IOrderService orderService;
    @Autowired
    private RedisTemplate redisTemplate;


    /**
     * 这里实现消费 死信队列中的消息
     * @param orderPayDto
     * @param channel
     * @param message
     */
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(
                    value = "order-dead-letter-queue",  // 订单队列？
                    durable = "true"),
            exchange = @Exchange(
                    value = "order-dead-letter-exchange", durable = "true", //交换机
                    type = ExchangeTypes.TOPIC),
            key = "dead.letter.order")
    )
    // 死信队列消费的业务流程
    // @Payload 接受  消费这 的 消息,把json字符串转成对象
    //  注意需要配置转换器

    // 1. 从MQ  拿到消息的消息
    // 2. 判断OrderVo的状态如果是0, 
    //    修改订单状态为5  无效订单
    //3.  redis中的库存需要还原
    public void handleOrder(@Payload OrderPayDto orderPayDto, Channel channel, Message message) {
        log.info("消费死信队列中的超时消息 {}",orderPayDto);
        //判断从mq中获取到的超时数据，订单的状态是否为待支付，如果为待支付状态，则更新订单失效。
        OrderVo orderVo = orderService.findByOrderSn(orderPayDto.getOrderSn());

        // 只有超时的订单才未付款,全改了,还有其他方式进来的消息
        //如果付款了 就是 其他 1 ，2  这里只处理未付款(很长时间)
        if (orderVo.getStatus().equals(OrderConstant.ORDER_STATUS_UNPAY)) {//0待付款
            log.info("订单失效,修改订单状态为5，无效订单");
            LambdaUpdateWrapper<Order> updateWrapper = Wrappers.lambdaUpdate();
            updateWrapper.set(Order::getStatus, OrderConstant.ORDER_STATUS_INVALID);//已失效
            updateWrapper.eq(Order::getOrderSn, orderPayDto.getOrderSn());
            orderService.update(updateWrapper);
            //将redis中扣减的库存，还原
            redisTemplate.opsForList().leftPush(
                    "product:kill:count:" + orderPayDto.getPromotionId(),
                    orderPayDto.getProductId());
        }
        try {
            //手动应答

            log.info("channel.basicAck start");
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
            log.info("channel.basicAck end");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}